#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";

// 构建报文
// "size""\n""x + y""\n"
std::string Encode(std::string &content)
{
    std::string package = std::to_string(content.size());
    package += protocol_sep;
    package += content;
    package += protocol_sep;

    return package;
}
// 拆解报文
// "size""\n""x + y""\n"
bool Decode(std::string &package, std::string &content)
{
    // 截取运算式的长度
    std::size_t pos = package.find(protocol_sep);
    if (pos == std::string::npos)
        return false;

    // 截取运算式的长度值
    std::string len_str = package.substr(0, pos);
    // 将运算式的长度值转换为整型
    size_t len = std::stoi(len_str);
    // 报文总长度
    size_t total_len = len_str.size() + len + 2;
    if (package.size() < total_len)
        return false;

    // 截取运算式
    content = package.substr(pos + 1, len);

    // 移除报文
    package.erase(0, total_len);

    return true;
}
// 运算式
class Request
{
public:
    Request(int data1, int data2, char oper)
        : x(data1), y(data2), op(oper)
    {
    }
    Request()
    {
    }
    // 构建运算式：序列化
    // "x + y"
    bool Serialize(std::string &out)
    {
#ifdef MySelf
        std::string s = std::to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += std::to_string(y);

        out = s;

        return true;
#else
        Json::Value root;
        root["x"] = x;
        root["y"] = y;
        root["op"] = op;
        // Json::FastWriter w;
        Json::StyledWriter w;
        out = w.write(root);

        return true;
#endif
    }
    // 拆解运算式：反序列化
    bool Deserialize(const std::string &in)
    {
#ifdef MySelf
        // 截取第一个操作数
        size_t left = in.find(blank_space_sep);
        if (left == std::string::npos)
            return false;
        std::string part_x = in.substr(0, left);

        // 截取第二个操作数
        size_t right = in.rfind(blank_space_sep);
        if (right == std::string::npos)
            return false;
        std::string part_y = in.substr(right + 1);

        // 截取运算符
        if (left + 2 != right)
            return false;
        op = in[left + 1];

        // 字符串转整型
        x = std::stoi(part_x);
        y = std::stoi(part_y);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in,root);

        x = root["x"].asInt();
        y = root["y"].asInt();
        op = root["op"].asInt();

        return true;
#endif
    }
    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x << op << y << "=?" << std::endl;
    }

public:
    int x;
    int y;
    char op;
};
// 运算结果
class Response
{
public:
    Response(int res, int c)
        : _result(res), _code(c)
    {
    }
    Response()
    {
    }
    // 构建结果：序列化
    // "result"" ""code"
    bool Serialize(std::string &out)
    {
#ifdef MySelf
        std::string s = std::to_string(_result);
        s += blank_space_sep;
        s += std::to_string(_code);
        out = s;

        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        
        // Json::FastWriter w;
        Json::StyledWriter w;
        out = w.write(root);

        return true;
#endif
    }
    // 拆解结果：反序列化
    bool Deserialize(const std::string &in)
    {
#ifdef MySelf
        // 截取result和code
        size_t pos = in.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;
        std::string part_left = in.substr(0, pos);
        std::string part_right = in.substr(pos + 1);

        // 字符串转整型
        _result = std::stoi(part_left);
        _code = std::stoi(part_right);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in,root);

        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
#endif
    }
    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << _result << ", code: " << _code << std::endl;
    }

public:
    int _result;
    int _code; // 0:可信，否则!0具体是多少，表明对应的错误原因
};